from pyglons.state import State, stop
from pyglons import g

import pyglet
from pyglet.gl import *
from pyglet.window import key

import logging 
log = logging.getLogger(__name__)

__all__ = ['PyglonsBaseState', 'update_time']


def update_time(update_time):
    """ decorator to set update time for an on_update event """
    def decor(func):
        func.update_time = update_time
        return func
    return decor


class PyglonsBaseState(State):
    """ Pyglons base state class provided as a default.

    On child classes you can set create_keyStateHandler as a class
    attribute to have a pyglet.window.key.KeyStateHandler created
    for you as self.keys. eg::

        class MyState(BaseState):   
            create_keyStateHandler = True

    on_enter() will automatically register event handlers 
    for any functions named like events on the class. window.push_handlers()
    is called before adding events and window.pop_handlers() is called
    on on_exit(). eg:

        class MyState(BaseState):
            def on_close(self):
                # this will be registered when this state is made 
                # active and removed when this state is made inactive
                ...

    on_key_press is by default setup to pop the current state when escape 
    is pressed. 

    Any methods with a 'update_time' attribute will be scheduled using 
    the value as the schedule interval. You can use the 'update_time()'
    decorator to easily add this attribute. If the class has an 
    on_update method, this will automatically be given the update time 
    of 0.1 unless it has already been set. 
    """

    create_keyStateHandler = False

    def __init__(self, window=None):
        self.window = window or g.app.window

    def on_enter(self):
        log.debug("%s on_enter" % self)

        win = self.window

        if self.create_keyStateHandler:
            self.keys = key.KeyStateHandler()
            win.push_handlers(self.keys)
        #self.on_resize(win.width, win.height)

        win.push_handlers()
        for event_type in win.event_types:
            if hasattr(self, event_type):
                win.set_handler(event_type, getattr(self, event_type))

        # automatically add to the scheduler anything that has an 
        # 'update_time' attribute.
        # on_update methods are treated specially and the update_time
        # attribute is automatically added
        self._scheduled_funcs = []
        if hasattr(self, 'on_update'):
            t = getattr(self.on_update, 'update_time', 0.1)
            pyglet.clock.schedule_interval(self.on_update, t)
            self._scheduled_funcs.append(self.on_update)
            for name in dir(self):
                thing = getattr(self, name)
                if callable(thing) and hasattr(thing, 'update_time'):
                    pyglet.clock.schedule_interval(thing, getattr(thing, 'update_time'))
                    self._scheduled_funcs.append(thing)

    def on_exit(self):
        log.debug("%s on_exit" % self)

        self.window.pop_handlers()

        if self.create_keyStateHandler and hasattr(self, 'keys'):
            self.window.pop_handlers()
            del self.keys

        for func in self._scheduled_funcs:
            pyglet.clock.unschedule(func)

    def on_close(self):
        stop()
    
